package boot.handler;

import boot.entity.Teacher;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/**
 * @author HLF
 * @date 2022/4/10 22:05
 */
@Aspect
@Component
public class BootAspect {
    @Pointcut(value = "execution(* *..service..SomeServiceImpl.*(..))")
    //@Pointcut(value = "execution(* boot.service.SomeServiceImpl.*(..))")
    public void myPointcut() {
    }

    @Before(value = "myPointcut()")
    public void before(JoinPoint joinPoint) {
        System.out.println("方法签名：" + joinPoint.getSignature());
        System.out.println("方法名：" + joinPoint.getSignature().getName());

        Object[] args = joinPoint.getArgs();
        for (Object arg : args) {
            System.out.println("目标方法的参数：" + arg);
        }
        System.out.println("==================================");

        System.out.println("1.@Before 在目标方法之前执行！");
    }

    @AfterReturning(value = "myPointcut()", returning = "result")
    public void after(JoinPoint joinPoint, Object result) {
        //修改目标方法的返回值(如果目标方法的返回值类型是String或者基本数据类型则不会被更改，引用数据类型会被修改)
        if (result instanceof String) {
            result = "修改后的目标方法的返回值";
        } else if (result instanceof Teacher) {
            ((Teacher) result).setName("修改后的Teacher-name"); //会修改成功，仅修改属性值，未改变result的引用地址
            //result = new Teacher("修改后的返回值Teacher引用数据类型", 21); //这样不能成功，不能修改result的引用地址
        }
        System.out.println("2.@AfterReturning 在目标方法执行之后执行！");
    }

    @Around(value = "myPointcut()")
    public Object around(ProceedingJoinPoint pjp) {
        System.out.println("3.@Around 在目标方法执行之前执行！");

        //定义目标方法的返回值(无论是什么类型，都可以被修改)
        Object result = null;

        //执行目标方法
        try {
            result = pjp.proceed();
        } catch (Throwable e) {
            e.printStackTrace();
        }

        System.out.println("3.@Around 在目标方法执行之后执行！");

        return result;
    }
}
